import sys

from twisted.internet import reactor
from twisted.python.log import startLogging
from twisted.internet.defer import Deferred
from pywow import realmserver, realmclient, errors
import time

debug = False
myusername = 'kreved'
mypassword = 'matan'
myhost = 'localhost'
# set delay>0, to do packets protocol crash test:)
# it will emulate slow link, and transmit 1 byte per $delay
delay = 0

def slow_send(f, s):
 for c in s:
  reactor.callFromThread(f.write, c)
  time.sleep(delay)


startLogging(sys.stdout)

class myrealmserverproto(realmserver.RealmServerProtocol):
 def connectionMade(self):
  self.debug = debug
  realmserver.RealmServerProtocol.connectionMade(self)
  peer = self.transport.getPeer()
  print "Accepted connection from %s:%s." % (peer.host, peer.port)
 def connectionLost(self, reason):
  realmserver.RealmServerProtocol.connectionLost(self, reason)
  peer = self.transport.getPeer()
  print "Client '%s:%s' disconnected." % (peer.host, peer.port)
 def send(self, packet):
  if delay == 0: self.transport.write(packet.pack())
  else: reactor.callInThread(slow_send, self.transport, packet.pack())

class myrealmserver(realmserver.RealmServerFactory):

 protocol = myrealmserverproto

 def getSV(self, username):
  """return salt and verifier for specified user
  string: username
  tuple: (string:salt, long:verifier)

  here we use const username/password
  """
  u = myusername.upper()
  p = mypassword.upper()
  if username == u: return self.generateSV(u, p)
  else: raise errors.NoSuchUser, username
 def isBanned(self, ip, username):
  """
  Check IP and username for Ban
  
  This function returns True, if user or IP is banned
  we ban only user 'BADUSER' (for test)
  """
  return username == 'BADUSER'
 def getRealmList(self, username):
  """
  should return list of realms
  each realm is tuple:
  (server_type, lock, status, name, address, populationLevel, charactersCount)
   server_type: 0 = NORMAL; 1 = PVP; 6 = RP; 8 = RPPVP
   lock: 1 - locked; 0 - unlocked
   status: 0 - online, 2 - offline
   name: [string] name of realm
   address: [string] ip:port
   populationLevel: = population / pLimit * 2
   charactersCount: count of this username's chars in this realm
  """
  d = Deferred()
  d.callback([(8, 0, 0, 'Popular Server', '127.0.0.1:3725', 2, 3),
  (1, 0, 0, 'Not So Popular Server', '127.0.0.1:3728', 0.5, 1),
  (6, 0, 0, 'Unpopular Server', '127.0.0.1:3729', 0.1, 0),
  (0, 0, 2, 'Fallen Server', '127.0.0.1:3726', 0, 0),
  (6, 1, 0, 'RP Server [locked]', '127.0.0.1:3727', 0.4, 0)])
  return d


class myrealmclientproto(realmclient.RealmClientProtocol):
 def connectionMade(self):
  self.debug = debug
  print "Connected to server."
  realmclient.RealmClientProtocol.connectionMade(self)
 def send(self, packet):
  if delay == 0: self.transport.write(packet.pack())
  else: reactor.callInThread(slow_send, self.transport, packet.pack())

class myrealmclient(realmclient.RealmClientFactory):
 protocol = myrealmclientproto
 def onRealmList(self, realms, K):
  """This function is called when we have received realm list,
  here we should select one realm, and connect to
  
  In this demo we just print result to stdout
  """
  print "realmlist received:\n %s" % '\n '.join(map(repr, realms))
  print "Session key is %s" % hex(K)


server = myrealmserver()
client = myrealmclient()
client.setAuthData(myusername, mypassword)

def startClient():
 reactor.connectTCP(myhost, 3724, client, 5)
 
reactor.listenTCP(3724, server)
reactor.callLater(1, startClient)

reactor.run()
